////////////////////////////////////////////////////////////////////////////////
// This file is part of the Mist compiler.                                    //
//                                                                            //
// Copyright (C) 2008, 2009 The Mist project                                  //
//                                                                            //
// For a list of contributors, see the COMMITTERS file.                       //
//                                                                            //
// The Mist compiler is free software: you can redistribute it and/or modify  //
// it under the terms of the GNU General Public License as published by       //
// the Free Software Foundation, either version 3 of the License, or          //
// (at your option) any later version.                                        //
//                                                                            //
// The Mist compiler is distributed in the hope that it will be useful,       //
// but WITHOUT ANY WARRANTY; without even the implied warranty of             //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              //
// GNU General Public License for more details.                               //
//                                                                            //
// You should have received a copy of the GNU General Public License          //
// in the COPYING file. If not, see <http://www.gnu.org/licenses/>.           //
////////////////////////////////////////////////////////////////////////////////

///
/// \file
/// Contains the Location class.
///

#ifndef LOCATION_HPP
#define LOCATION_HPP

////////////////////////////////////////////////////////////////////////////////
// Includes                                                                   //
////////////////////////////////////////////////////////////////////////////////

#include <string>
using std::string;

#include <ostream>
using std::ostream;

#include <boost/operators.hpp>
using boost::equivalent;
using boost::equality_comparable;

#include "position.hpp"
#include "common/outputproducer.hpp"

namespace yy { class location; }

////////////////////////////////////////////////////////////////////////////////
// Location Class                                                             //
////////////////////////////////////////////////////////////////////////////////

/// A location in the source-code.
///
class Location : equivalent<Location, equality_comparable<Location> >, public OutputProducer {
	public:
		
		/// Construct a new Location, initialized to \a l.
		///
		Location(
			const yy::location& l ///< a code location generated by Bison
		);
		
		/// Construct a new Location, from \a b to \a e.
		///
		Location(
			const Position& b, ///< the first position of the new Location
			const Position& e  ///< the last  position of the new Location
		);
		
		/// Construct a new Location, from \a b.begin to \a e.end.
		///
		Location(
			const Location& b, ///< a prefix of the new Location
			const Location& e  ///< a suffix of the new Location
		);
		
		/// Construct a new Location.
		///
		Location(
			string file,      ///< the           file   of the new Location
			uint beginLine,   ///< the beginning line   of the new Location
			uint beginColumn, ///< the beginning column of the new Location
			uint endLine,     ///< the ending    line   of the new Location
			uint endColumn    ///< the ending    column of the new Location
		);
		
		/// Construct a new Location.
		///
		Location(
			string file,      ///< the           file   of the new Location
			uint line,        ///< the           line   of the new Location
			uint beginColumn, ///< the beginning column of the new Location
			uint endColumn    ///< the ending    column of the new Location
		);
		
		/// Construct a new Location.
		///
		Location(
			string file, ///< the file   of the new Location
			uint line,   ///< the line   of the new Location
			uint column  ///< the column of the new Location
		);
		
		/// \return true , if \a this location lies inside the \a other
		///         false, otherwise
		///
		bool is_in(const Location& other) const;
		
		/// Send \a this location to output-stream \a stream.
		///
		ostream& send_to_stream(ostream& stream) const;
		
		/// Order two locations lexicographically
		///
		bool operator<(const Location& other) const;
		
		Position begin; ///< the first position of this location
		Position end;   ///< the last  position of this location
};

#endif // LOCATION_HPP
